package xcmg.device.service.agentApply;

import com.github.pagehelper.PageInfo;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import xcmg.device.dao.entity.agentApply.AgentApplyAttachment;
import xcmg.device.dao.entity.agentApply.AgentApplyDO;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.agentApply.AgentApplyAttachmentMapper;
import xcmg.device.dao.mapper.agentApply.AgentApplyMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.enums.AgentApplyStatusEnum;
import xcmg.device.service.vo.agentApply.AgentApplyVO;
import xcmg.device.service.warehouse.CommonService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class AgentApplyService {


    @Autowired
    private AgentApplyMapper agentApplyMapper;

    @Autowired
    private AgentApplyAttachmentMapper agentApplyAttachmentMapper;

  @Autowired
  private FastGenClient fastGenClient;

  @Autowired
  private CommonService commonService;

  @Autowired
  private CompanyInfoMapper companyInfoMapper;

  @Autowired
  private HttpServletResponse response;

  @Value("${spring.file.download.path}")
  private String filePath;

  private static final String FILE_UPLOAD_PATH = "agent_apply_attach/";

  public PageCommonVO list(SearchCommonVO<AgentApplyVO> condition) {
    PageCommonVO<AgentApplyVO> pageCommonVO = new PageCommonVO<>();
      PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
    List<AgentApplyDO> applyDOS = agentApplyMapper.list(condition.getFilters());
    List<AgentApplyVO> applyVOS = new ArrayList<>();
    AgentApplyVO applyVO;
    for (AgentApplyDO applyDO : applyDOS) {
      applyVO = new AgentApplyVO();
      BeanUtils.copyProperties(applyDO, applyVO);
      applyVOS.add(applyVO);
    }
    pageCommonVO.setPageInfo(new PageInfo(applyDOS));
    pageCommonVO.setPageInfoList(applyVOS);
    return pageCommonVO;
  }

  public AgentApplyVO item(String id) {
    AgentApplyDO agentApplyDO = agentApplyMapper.getById(id);
    if (null == agentApplyDO) {
      return new AgentApplyVO();
    }
    AgentApplyVO agentApplyVO = new AgentApplyVO();
    agentApplyVO
        .setStatusDesc(AgentApplyStatusEnum.getByStatus(agentApplyDO.getStatus()).getDesc());
    BeanUtils.copyProperties(agentApplyDO, agentApplyVO);
    List<AgentApplyAttachment> agentApplyAttachments = agentApplyAttachmentMapper.listByApplyId(id);
    List<AgentApplyAttachment> attachmentStartList = new ArrayList<>();
    List<AgentApplyAttachment> attachmentEndList = new ArrayList<>();
    agentApplyAttachments.forEach(x->{
      Integer type = x.getType();
      if (type == 0){
        attachmentStartList.add(x);
      }else{
        attachmentEndList.add(x);
      }
    });
    agentApplyVO.setAttachmentList(attachmentStartList);
    agentApplyVO.setAttachmentEndList(attachmentEndList);
    return agentApplyVO;
  }

  @Transactional(rollbackFor = Exception.class)
  public String save(AgentApplyVO applyVO) throws Exception {
    AgentApplyDO applyDO = new AgentApplyDO();
    ActionResult<String> textResult = fastGenClient.textGuid();
    String applyId = textResult.getValue();
    applyDO.setId(applyId);
    applyDO.setTitle(applyVO.getTitle());
    applyDO.setApplyType(applyVO.getApplyType());
    applyDO.setStatus(applyVO.getStatus());
    applyDO.setApplyDesc(applyVO.getApplyDesc());
    applyDO.setDeleteFlag(AgentApplyVO.DELETE_FLAG_NO);
    applyDO.setOrgId(applyVO.getOrgId());
    applyDO.setOrgName(getComNameByOrgId(applyVO.getOrgId()));
    applyDO.setReceiveOrgId(applyVO.getReceiveOrgId());
    applyDO.setReceiveOrgName(getComNameByOrgId(applyVO.getReceiveOrgId()));
    applyDO.setCreateId(applyVO.getCreateId());
    applyDO.setCreateName(commonService.getUserName(applyVO.getCreateId()));
    applyDO.setCreateTime(new Date());
    agentApplyMapper.insert(applyDO);
    saveAttachments(applyVO.getFiles(), applyId);
    return applyId;
  }

  private String getComNameByOrgId(String orgId) throws Exception {
    CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
    if (null == companyInfoDO) {
      throw new Exception("未查询到该公司");
    }
    return companyInfoDO.getCompanyName();
  }

  private void saveAttachments(List<MultipartFile> files, String applyId)
      throws Exception {
    if (CollectionUtils.isEmpty(files)) {
      return;
    }
    for (MultipartFile file : files) {
      agentApplyAttachmentMapper.insert(uploadAttachment(file, applyId,0));
    }
  }

  /**
   * 单个文件上传
   */
  @Transactional(rollbackFor = Exception.class)
  public void uploadFile(String applyId, MultipartFile file,Integer type) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }
    if (AgentApplyStatusEnum.FINISH.getStatus().equals(applyDO.getStatus())) {
      throw new Exception("状态已完结，不能上传附件");
    }
    agentApplyAttachmentMapper.insert(uploadAttachment(file, applyId,type));
  }

  private AgentApplyAttachment uploadAttachment(MultipartFile file, String applyId,Integer type)
      throws Exception {
    AgentApplyAttachment attachment = new AgentApplyAttachment();
    ActionResult<String> textResult = fastGenClient.textGuid();
    String fileSysId = textResult.getValue();
    String fileName;
    try {
      fileName = fileSysId + file.getOriginalFilename()
          .substring(file.getOriginalFilename().lastIndexOf("."));
      FileUtil.uploadFile(file, getFilePath(applyId), fileName);

      attachment.setId(fileSysId);
      attachment.setApplyId(applyId);
      attachment.setFileName(new String(file.getOriginalFilename().getBytes("utf-8")));
      attachment.setSysFileName(fileName);
      attachment.setCreateTime(new Date());
      attachment.setType(type);
    } catch (Exception e) {
      LogHelper.fatal("AgentApplyService#uploadAttach is error.", e);
      throw new Exception(e);
    }
    return attachment;
  }

  /**
   * 删除单个文件
   */
  @Transactional(rollbackFor = Exception.class)
  public void deleteAttachment(String attachId, String applyId) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }
    if (AgentApplyStatusEnum.FINISH.getStatus().equals(applyDO.getStatus())) {
      throw new Exception("状态已完结，不能删除附件");
    }
    AgentApplyAttachment attachment = agentApplyAttachmentMapper.getById(attachId);
    if (null == attachment) {
      throw new Exception("文件不存在");
    }
    FileUtil.deleteFile(getFilePath(applyId), attachment.getSysFileName());
    agentApplyAttachmentMapper.deleteById(attachId);
  }

  private String getFilePath(String applyId) {
    return filePath + FILE_UPLOAD_PATH + applyId + "/";
  }

  public void revoke(String applyId) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }
    AgentApplyStatusEnum statusEnum = AgentApplyStatusEnum.getByStatus(applyDO.getStatus());
    if (!statusEnum.isCanRevoke()) {
      throw new Exception("当前状态不能撤回");
    }
    applyDO.setStatus(AgentApplyStatusEnum.DRAFT.getStatus());
    agentApplyMapper.update(applyDO);
  }

  public void audit(AgentApplyVO applyVO, Integer auditType) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyVO.getId());
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }

    AgentApplyStatusEnum statusEnum = AgentApplyStatusEnum.getByStatus(applyDO.getStatus());
    if (!statusCanAudit(auditType, statusEnum)) {
      throw new Exception("当前状态不能" + statusEnum.getDesc());
    }
    applyDO.setFirstAdvice(applyVO.getFirstAdvice());
    applyDO.setFinalAdvice(applyVO.getFinalAdvice());
    applyDO.setStatus(applyVO.getStatus());
    applyDO.setAuditId(applyVO.getAuditId());
    if (null != applyVO.getExhibitionStatus() && 0 != applyVO.getExhibitionStatus()){
      applyDO.setExhibitionStatus(applyVO.getExhibitionStatus());
    }
    applyDO.setAuditName(commonService.getUserName(applyVO.getAuditId()));
    applyDO.setAuditTime(new Date());
    agentApplyMapper.update(applyDO);
  }

  /**
   * 当前状态是否允许审核。必须是待初审或者初审通过状态才允许审核
   */
  private Boolean statusCanAudit(Integer auditType, AgentApplyStatusEnum statusEnum)
      throws Exception {
    //初审、终审对应的状态限制
    if ((AgentApplyVO.FIRST_AUDIT_TYPE.equals(auditType) && !statusEnum.isCanFirstAudit())
        || (AgentApplyVO.FINAL_AUDIT_TYPE.equals(auditType) && !statusEnum.isCanFinalAudit())) {
      return false;
    }
    // 返回修改时的状态限制
    if (AgentApplyVO.AUDIT_RETURN.equals(auditType) && (!statusEnum.isCanFirstAudit() && !statusEnum
        .isCanFinalAudit())) {
      return false;
    }
    return true;
  }

  /**
   * 删除申请。主表数据软删除，附件表不动，也方便数据追溯
   */
  public void deleteApply(String applyId, String userId) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (null == applyDO) {
      return;
    }
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }
    AgentApplyStatusEnum statusEnum = AgentApplyStatusEnum.getByStatus(applyDO.getStatus());
    if (!statusEnum.isCanDelete()) {
      throw new Exception("当前状态不能删除");
    }
    applyDO.setDeleteId(userId);
    applyDO.setDeleteName(commonService.getUserName(userId));
    applyDO.setDeleteTime(new Date());
    applyDO.setDeleteFlag(AgentApplyVO.DELETE_FLAG_YES);
    agentApplyMapper.update(applyDO);
  }


  /**
   * 完结
   */
  public void finish(String applyId, String userId) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (null == applyDO) {
      return;
    }
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }

    applyDO.setUpdateId(userId);
    applyDO.setUpdateName(commonService.getUserName(userId));
    applyDO.setUpdateTime(new Date());
    applyDO.setExhibitionStatus(AgentApplyVO.EXHIBITION_STATUS_FINISH);
    agentApplyMapper.update(applyDO);
  }

  /**
   * 驳回
   */
  public void reject(String applyId, String userId) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyId);
    if (null == applyDO) {
      return;
    }
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }

    applyDO.setUpdateId(userId);
    applyDO.setUpdateName(commonService.getUserName(userId));
    applyDO.setUpdateTime(new Date());
    applyDO.setExhibitionStatus(AgentApplyVO.EXHIBITION_STATUS_OVERRULE);
    agentApplyMapper.update(applyDO);
  }

  public List<CompanyInfoDO> listSapComByDealer(String orgId) {
    return companyInfoMapper.listSapComByDealer(orgId);
  }

  public void update(AgentApplyVO applyVO) throws Exception {
    AgentApplyDO applyDO = agentApplyMapper.getById(applyVO.getId());
    if (applyDO.isDeleted()) {
      throw new Exception("不能操作已作废的单据");
    }
    AgentApplyStatusEnum statusEnum = AgentApplyStatusEnum.getByStatus(applyDO.getStatus());
    if (!statusEnum.isCanUpdate()) {
      throw new Exception("当前状态不能编辑");
    }
    applyDO.setTitle(applyVO.getTitle());
    applyDO.setApplyDesc(applyVO.getApplyDesc());
    applyDO.setStatus(applyVO.getStatus());
    applyDO.setReceiveOrgId(applyVO.getReceiveOrgId());
    applyDO.setReceiveOrgName(getComNameByOrgId(applyVO.getReceiveOrgId()));
    applyDO.setUpdateId(applyVO.getCreateId());
    applyDO.setUpdateName(commonService.getUserName(applyVO.getCreateId()));
    applyDO.setUpdateTime(new Date());
    agentApplyMapper.update(applyDO);
  }


  public ErrorCode exhibitionEndCommit(AgentApplyVO applyVO){
    AgentApplyDO applyDO = new AgentApplyDO();
    applyDO.setId(applyVO.getId());
    applyDO.setExhibitionStatus(AgentApplyVO.EXHIBITION_STATUS_END);
    applyDO.setUpdateId(applyVO.getCreateId());
    applyDO.setUpdateName(commonService.getUserName(applyVO.getCreateId()));
    applyDO.setUpdateTime(new Date());
    return  agentApplyMapper.update(applyDO) > 0?ErrorCode.Success:ErrorCode.Failure;
  }

  /**
   * 单个下载附件
   */
  public void downloadAttach(String attachId, String applyId) throws Exception {
    AgentApplyAttachment attachment = agentApplyAttachmentMapper.getById(attachId);
    FileUtil .downLoadFileUseOldName(response, getFilePath(applyId), attachment.getSysFileName(), new String(attachment.getFileName().getBytes("utf-8")));
  }
}
